﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Common.Constants;
using Common.Interface;
using EntityFrameworkExtension;
using EntityFrameworkExtension.Interface;
using MainProcessor.ContextProcessor;
using MainProcessor.Interface;
using MainProcessor.Processors;
using NUnit.Framework;
using Rhino.Mocks;
using Common.Helper;

namespace Test.Main.ContextProcessor
{
    [TestFixture]
    public class ReplacedInteface2ProcessorTests
    {
        private IDataCache cache;
        private IEfContext efContext;
        private IDataController dataController;
        private ReplacedInteface2Processor replacedInteface2Processor;
        private IEntityFactory entityFactory;
        private IEntityFactory concreteEntityFactory;
        private List<IChild> children;

        [SetUp]
        public void SetUp()
        {
            efContext = MockRepository.GenerateMock<IEfContext>();
            dataController = MockRepository.GenerateMock<IDataController>();
            entityFactory = MockRepository.GenerateMock<IEntityFactory>();
            cache = MockRepository.GenerateMock<IDataCache>();

            concreteEntityFactory = new EntityFactory();

            var xml = XElement.Parse(ConstantXml.TestString);
            PopulateShareClassSeries(xml);

            replacedInteface2Processor = new ReplacedInteface2Processor(cache, dataController,  entityFactory);
        }

        private void PopulateShareClassSeries(XElement xml)
        {
            var type = (from parentContainer in xml.Descendants(XmlConstants.ParentContainer)
                        select parentContainer).First();
            children = concreteEntityFactory.CreateChildren(type);
        }

        [TearDown]
        public void Teardown()
        {
            dataController.VerifyAllExpectations();
            efContext.VerifyAllExpectations();
            cache.VerifyAllExpectations();
            entityFactory.VerifyAllExpectations();
        }

        [Test]
        public void NewShareClassShouldBePickedUpAndInserted()
        {
            var xml = XElement.Parse(ConstantXml.TestString);


            efContext.Expect(x => x.GetObjectList<ReplacedInteface2>(null)).IgnoreArguments().Return(Enumerable.Empty<ReplacedInteface2>().ToList()).Repeat.AtLeastOnce();
            
            dataController.Expect(x => x.GetGuidIntMappings1(Arg<int>.Matches(y => y == MappingId), Arg<IEfContext>.Is.Anything)).Return(FundGuid).Repeat.Times(2);
            entityFactory.Expect(x => x.CreateChildren(null)).IgnoreArguments().Return(children);

            efContext.Expect(x => x.AddToObjectList(Arg<ReplacedInteface2>.Matches(y => y.ChildGuid == ShareClassGuid1
                && y.Name == "Parent Child"
                && y.ParentGuid == FundGuid
                && (y.uniqueChildProperty.HasValue && y.uniqueChildProperty.Value)
                && y.CommonChildProperty == "USD"
                

                ))).Repeat.Once();

            efContext.Expect(x => x.AddToObjectList(Arg<ReplacedInteface2>.Matches(y => y.ChildGuid == ShareClassGuid2
                && y.Name == "Lower Child"
                && y.ParentGuid == FundGuid
                && (y.uniqueChildProperty.HasValue && !y.uniqueChildProperty.Value)
                && y.CommonChildProperty == "USD"

                ))).Repeat.Once();
            
            replacedInteface2Processor.ExtractXml(xml);

            replacedInteface2Processor.PopulateEf(efContext);
        }

        [Test]
        public void ExistingShareClassesShouldBeUpdated()
        {
            var xml = XElement.Parse(ConstantXml.TestString.Replace("<CommonChildProperty1>USD</CommonChildProperty1>", "<CommonChildProperty1>ZAR</CommonChildProperty1>"));

            PopulateShareClassSeries(xml);

            efContext.Expect(x => x.GetObjectList<ReplacedInteface2>(null)).IgnoreArguments().Return(ShareClasses).Repeat.Once();
            efContext.Expect(x => x.Delete(Arg<ReplacedInteface2>.Matches(y => y.ChildGuid == ShareClassGuid3))).Repeat.Once();

            dataController.Expect(x => x.GetGuidIntMappings1(Arg<int>.Matches(y => y == MappingId), Arg<IEfContext>.Is.Anything)).Return(FundGuid).Repeat.Times(2);

            entityFactory.Expect(x => x.CreateChildren(null)).IgnoreArguments().Return(children);
            
            
            
            replacedInteface2Processor.ExtractXml(xml);
            replacedInteface2Processor.PopulateEf(efContext);

            Assert.AreEqual(ShareClasses[0].CommonChildProperty, "ZAR");
            Assert.IsTrue(ShareClasses[0].uniqueChildProperty.HasValue && ShareClasses[0].uniqueChildProperty.Value);

        }


      

        private const int MappingId = 321;
        private static readonly Guid FundGuid = Guid.NewGuid();
        private static readonly Guid ShareClassGuid1 = new Guid("720d3c24-3fe9-4ce1-ae5c-a6a7b949c773");
        private static readonly Guid ShareClassGuid2 = new Guid("E0114A21-2F46-4E36-B563-F0955F1BB43A");
        private static readonly Guid ShareClassGuid3 = Guid.NewGuid();
        private static readonly List<ReplacedInteface2> ShareClasses = new List<ReplacedInteface2> { new ReplacedInteface2 { Name = "D.E. Shaw & Co. (GM-GT) - LP", ParentGuid = FundGuid, ChildGuid = ShareClassGuid1 } 
                                                                                        ,new ReplacedInteface2 { ParentGuid = FundGuid, ChildGuid = ShareClassGuid2 }
                                                                                        ,new ReplacedInteface2 { ParentGuid = FundGuid, ChildGuid = ShareClassGuid3 }  };
       

      
    }
}
